package com.qfmy.common.utils;

import com.qfmy.common.login.GraphicCodeResult;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;

/**
 * 图形验证码工具类
 * 支持生成带干扰线、噪点、随机旋转字符的验证码图片（Base64格式）及对应验证码文本
 */
public final class GraphicCodeUtil {

    // 私有构造方法，禁止实例化
    private GraphicCodeUtil() {
        throw new AssertionError("工具类不允许实例化");
    }

    // 字符集（排除易混淆字符：0/O, 1/l, I）
    private static final String CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
    private static final Random RANDOM = new Random();

    /**
     * 生成图形验证码（默认配置）
     * @return 验证码结果（包含文本和Base64图片）
     */
    public static GraphicCodeResult generate() {
        // 默认配置：宽120，高40，4位字符，3条干扰线，30个噪点
        return generate(120, 40, 4, 3, 30);
    }

    /**
     * 生成图形验证码（自定义配置）
     * @param width 图片宽度
     * @param height 图片高度
     * @param codeLength 验证码字符长度
     * @param lineCount 干扰线数量
     * @param noiseCount 噪点数量
     * @return 验证码结果（包含文本和Base64图片）
     */
    public static GraphicCodeResult generate(int width, int height, int codeLength, int lineCount, int noiseCount) {
        // 1. 创建图片缓冲区
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = (Graphics2D) image.createGraphics();

        try {
            // 2. 设置绘图属性（抗锯齿）
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 3. 绘制背景（浅灰色）
            g2d.setColor(new Color(245, 245, 245));
            g2d.fillRect(0, 0, width, height);

            // 4. 设置字体（宋体加粗）
            Font font = new Font("宋体", Font.BOLD, height - 10); // 字体大小随高度自适应
            g2d.setFont(font);

            // 5. 生成并绘制随机字符
            StringBuilder codeBuilder = new StringBuilder();
            for (int i = 0; i < codeLength; i++) {
                // 随机选择字符
                int index = RANDOM.nextInt(CHAR_SET.length());
                char c = CHAR_SET.charAt(index);
                codeBuilder.append(c);

                // 随机颜色（深色，与背景区分）
                g2d.setColor(new Color(
                        RANDOM.nextInt(80) + 30,  // R（30-110）
                        RANDOM.nextInt(80) + 30,  // G（30-110）
                        RANDOM.nextInt(80) + 30   // B（30-110）
                ));

                // 随机旋转角度（-30° 到 30°）
                double angle = (RANDOM.nextInt(60) - 30) * Math.PI / 180;
                // 计算字符位置（平均分布，避免超出边界）
                int x = (width / codeLength) * i + 5; // 左间距5px
                int y = height - 10; // 底部间距10px

                // 保存当前绘图状态，旋转后恢复
                AffineTransform oldTransform = g2d.getTransform();
                g2d.rotate(angle, x, y);
                g2d.drawString(String.valueOf(c), x, y);
                g2d.setTransform(oldTransform);
            }

            // 6. 添加干扰线
            for (int i = 0; i < lineCount; i++) {
                g2d.setColor(new Color(
                        RANDOM.nextInt(150) + 50,  // R（50-200）
                        RANDOM.nextInt(150) + 50,  // G（50-200）
                        RANDOM.nextInt(150) + 50   // B（50-200）
                ));
                // 随机起点和终点
                int x1 = RANDOM.nextInt(width);
                int y1 = RANDOM.nextInt(height);
                int x2 = RANDOM.nextInt(width);
                int y2 = RANDOM.nextInt(height);
                g2d.drawLine(x1, y1, x2, y2);
            }

            // 7. 添加噪点
            for (int i = 0; i < noiseCount; i++) {
                g2d.setColor(new Color(
                        RANDOM.nextInt(200),  // R（0-200）
                        RANDOM.nextInt(200),  // G（0-200）
                        RANDOM.nextInt(200)   // B（0-200）
                ));
                // 随机位置画1x1像素点
                int x = RANDOM.nextInt(width);
                int y = RANDOM.nextInt(height);
                g2d.fillRect(x, y, 1, 1);
            }

            // 8. 转换为Base64图片字符串
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                ImageIO.write(image, "png", baos);
                byte[] imageBytes = baos.toByteArray();
                String imageBase64 = "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);
                return new GraphicCodeResult(codeBuilder.toString(), imageBase64);
            }

        } catch (IOException e) {
            throw new RuntimeException("生成图形验证码失败", e);
        } finally {
            // 释放资源
            g2d.dispose();
        }
    }



}